package com.league.blog.system.shiro;

import com.league.blog.mapper.UserMapper;
import com.league.blog.pojo.Permission;
import com.league.blog.pojo.Role;
import com.league.blog.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @author 黄豪琦
 */
@Slf4j
public class DefaultRealm extends AuthorizingRealm{

	private UserMapper userMapper;

	@Autowired
	public void setUserMapper(UserMapper userMapper) {
		this.userMapper = userMapper;
	}

	/**
	 * 获取授权信息
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
		//获取登录用户名
		User user = (User) principalCollection.getPrimaryPrincipal();

		User dbUser = userMapper.selectUserByAccountName(user.getAccountName());

		//添加角色和权限
		SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

		//添加用户拥有的角色以及角色所拥有的权限
		for(Role role : dbUser.getRoleList()){
			//添加角色
			simpleAuthorizationInfo.addRole(role.getRoleName());
			for(Permission permission : role.getPermissionList()){
				//添加权限
				simpleAuthorizationInfo.addStringPermission(permission.getPmsName());
			}

		}

		//添加用户直接拥有的权限
		for (Permission permission : dbUser.getPermissionList()){
			simpleAuthorizationInfo.addStringPermission(permission.getPmsName());
		}

		return simpleAuthorizationInfo;
	}


	/**
     * 获取身份验证信息
     * Shiro中，最终是通过 Realm 来获取应用程序中的用户、角色及权限信息的。
     *
     * @param authenticationToken 用户身份信息 token
     * @return 返回封装了用户信息的 AuthenticationInfo 实例
     */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
			throws AuthenticationException {
//		log.info("验证用户身份");
		//获取用户输入的信息

		String name = null;
		String password = null;
		try {
			name = authenticationToken.getPrincipal().toString();
			password = new String((char[]) authenticationToken.getCredentials());
		} catch (Exception e) {
			log.info("登录发生异常\t"+e.getMessage());
		}


		//根据登录名查出用户的信息
		User user = userMapper.selectUserByAccountName(name);


		if(user == null) {
			throw new UnknownAccountException("该用户不存在");
		}
		if(1 == user.getUserStatus()){
			throw new LockedAccountException("账号已被锁定，请联系管理员");
		}
		user.getRoleList().forEach(item ->{
			user.addPermission(item.getPermissionList());
		});
		return new SimpleAuthenticationInfo(user, user.getUserPassword(), ByteSource.Util.bytes("huanghq-salt"),
				getName());
	}

	/**
	 * 密码加密
	 * @param credentialsMatcher
	 */
	@Override
	public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
		HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
		matcher.setHashAlgorithmName("SHA-256");
		matcher.setHashIterations(1024);
		super.setCredentialsMatcher(matcher);
	}

	/**
	 * 清除当前用户的 授权缓存
	 * @param principals
	 */
	@Override
	public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
		log.info("清除当前用户的授权缓存");
		super.clearCachedAuthorizationInfo(principals);
	}

	/**
	 * 清除当前用户的 认证缓存
	 * @param principals
	 */
	@Override
	public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
		log.info("清除当前用户的认证缓存");
		super.clearCachedAuthenticationInfo(principals);
	}

	@Override
	public void clearCache(PrincipalCollection principals) {
		super.clearCache(principals);
	}

	/**
	 * 自定义方法：清除所有认证缓存
	 */
	public void clearAllCacheAuthenticationInfo(){
		log.info("清除所有认证缓存");
		getAuthenticationCache().clear();
	}

	/**
	 * 自定义方法：清除所有授权缓存
	 */
	public void clearAllCacheAuthorizationInfo(){
		log.info("清除所有授权缓存");
		getAuthorizationCache().clear();
	}

	/**
	 * 自定义方法：清除所有缓存
	 */
	public void clearAllCache(){
		log.info("清除所有的[认证缓存]和[授权缓存]");
		clearAllCacheAuthenticationInfo();
		clearAllCacheAuthorizationInfo();
	}
}
